#include "config.h"

#include <iostream>
#include <string>
#if CFG_HAVE_STD_RANGES
#include <ranges>
#endif

using namespace cfg;

// 示例程序 1：从内存构建对象，增加 Schema 规则，进行校验并读取值。
// 说明：
//  - 演示 set/merge 与 schema 校验（必填、类型、范围、枚举、pattern）。
//  - 成功路径打印最终值；失败路径打印错误集合（包含结构化字段）。
static void
print_error(const ConfigError & e)
{
    std::cerr << "[" << static_cast<int>(e.code) << "] " << e.message;
    if (!e.path.empty())
    {
        std::cerr << " path=";
#if CFG_HAVE_STD_RANGES
        for (char ch : e.path | std::views::join_with(std::string_view(".")))
        {
            std::cerr << ch;
        }
#else
        for (size_t i = 0; i < e.path.size(); ++i)
        {
            if (i > 0)
                std::cerr << ".";
            std::cerr << e.path[i];
        }
#endif
    }
    if (e.expected_type.has_value())
    {
        std::cerr << " expected_type=" << static_cast<int>(*e.expected_type);
    }
    if (e.actual_type.has_value())
    {
        std::cerr << " actual_type=" << static_cast<int>(*e.actual_type);
    }
    if (e.min_value.has_value())
    {
        std::cerr << " min=" << *e.min_value;
    }
    if (e.max_value.has_value())
    {
        std::cerr << " max=" << *e.max_value;
    }
    if (e.expected_pattern.has_value())
    {
        std::cerr << " pattern=\"" << *e.expected_pattern << "\"";
    }
    std::cerr << "\n";
}

int
main()
{
    Builder b;

    // 构建数据
    b.set("server.host", std::string("localhost"));
    b.set("server.port", int64_t(8080));
    b.set("server.mode", std::string("prod"));
    b.set("server.timeout", int64_t(15));
    b.set("user.email", std::string("alice@example.com"));

    // 添加规则
    SchemaRule r1;
    r1.path = "server.host";
    r1.required = true;
    r1.expected_type = SchemaValueType::String;
    SchemaRule r2;
    r2.path = "server.port";
    r2.required = true;
    r2.expected_type = SchemaValueType::Int64;
    r2.has_min = true;
    r2.min_value = 1;
    r2.has_max = true;
    r2.max_value = 65535;
    SchemaRule r3;
    r3.path = "server.mode";
    r3.expected_type = SchemaValueType::String;
    r3.enum_values = {std::string("dev"), std::string("prod")};
    SchemaRule r4;
    r4.path = "user.email";
    r4.expected_type = SchemaValueType::String;
    r4.regex_pattern = "^\\w+@example\\.com$";

    b.add_schema_rule(r1).add_schema_rule(r2).add_schema_rule(r3).add_schema_rule(r4);

    auto frozen = b.freeze();
    if (!frozen)
    {
        const auto & errs = frozen.error();
        std::cerr << "schema validation failed: " << errs.size() << " error(s)\n";
        for (const auto & e : errs)
            print_error(e);
        return 1;
    }

    View v(*frozen);
    auto host =
        v.lookup("server.host").and_then([](const View & sv) { return sv.get<std::string>(); });
    auto port = v.lookup("server.port").and_then([](const View & sv) { return sv.get<int64_t>(); });

    if (host && port)
    {
        std::cout << "Server: " << *host << ":" << *port << "\n";
    }
    else
    {
        std::cerr << "failed to read server.host/port\n";
    }

    return 0;
}
